package com.mayisoftware.mayioa.business.personal.impl.controller;

import com.mayisoftware.mayioa.business.flow.api.service.IFlowBaseService;
import com.mayisoftware.mayioa.business.personal.api.domain.*;
import com.mayisoftware.mayioa.business.personal.api.service.IPersonalSignService;
import com.mayisoftware.mayioa.business.personal.impl.serviceImpl.PersonalSignServiceImpl;
import com.mayisoftware.mayioa.business.plan.api.domain.*;
import com.mayisoftware.mayioa.business.plan.api.service.*;
import com.mayisoftware.mayioa.business.pool.api.domain.PoolMgrInfo;
import com.mayisoftware.mayioa.business.pool.api.service.IPoolManualService;
import com.mayisoftware.mayioa.common.api.base.AjaxResult;
import com.mayisoftware.mayioa.common.impl.config.Global;
import com.mayisoftware.mayioa.common.impl.utils.StringUtils;
import com.mayisoftware.mayioa.platform.api.domain.SysDictData;
import com.mayisoftware.mayioa.platform.api.domain.SysUser;
import com.mayisoftware.mayioa.platform.api.service.ISysDictDataService;
import com.mayisoftware.mayioa.platform.impl.util.FileUploadUtils;
import com.mayisoftware.mayioa.platform.impl.util.ShiroUtils;
import com.mayisoftware.mayioa.platform.impl.web.base.BaseController;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.flowable.engine.runtime.ProcessInstance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.util.*;

/**
 * 用户报名控制器
 */
@Controller
@RequestMapping("/personal/sign")
public class PersonalSignController extends BaseController{
    /**
     * URL前缀
     */
    private String prefix = "personal/sign";

    /**
     * 日志工具类
     */
    private static final Logger log = LoggerFactory.getLogger(PersonalSignController.class);

    /**
     * 计划绩效服务
     */
    @Autowired
    private IPlanArchService planArchService;

    /**
     * 计划自定义服务
     */
    @Autowired
    private IPlanCustomService planCustomService;

    /**
     * 计划课程服务
     */
    @Autowired
    private IPlanClassService planClassService ;

    /**
     * 数据字典服务
     */
    @Autowired
    private ISysDictDataService sysDictDataService;
    /**
     * 计划详情配置服务
     */
    @Autowired
    private IPlanConfigDetailService planConfigDetailService;

    /**
     * 计划配置服务
     */
    @Autowired
    private IPlanConfigService planConfigService;

    /**
     * 用户报名服务
     */
    @Autowired
    private IPersonalSignService personalSignService;

    /**
     * 流程控制服务
     */
    @Autowired
    private IFlowBaseService baseService;

    @RequiresPermissions("personal:sign:view")
    @GetMapping()
    public String user()
    {
        return prefix + "/sign";
    }

    @RequiresPermissions("personal:sign:list")
    @RequestMapping("/list")
    @ResponseBody
    public PersonPlan list()
    {
        PersonPlan result = new PersonPlan();
        SysUser user = ShiroUtils.getSysUser();
        // 读取可以参加的计划列表
        List<PlanConfig> planConfigs =planConfigService.selectPlanConfigByUserId(user.getUserId().longValue());

        if (CollectionUtils.isEmpty( planConfigs)){
            return result;
        }

        List<PersonalSign> planSigns = personalSignService.querySignListByUserId(user.getUserId().intValue());
        Set<Integer> joinedPlans = new HashSet<>();
        for (PersonalSign sign:planSigns){
            if (sign.getPerSignPlanId() != null){
                joinedPlans.add(sign.getPerSignPlanId());
            }
        }

        List<PersonDetailPlan> perPlanInfos = new ArrayList<>();

        //遍历每一个可以参加的计划
        for (PlanConfig planConfig:planConfigs){
            //未发布
            if (planConfig.getPlanCfgStatus().equalsIgnoreCase("0")){
                continue;
            }
            PersonDetailPlan personDetailPlan = new PersonDetailPlan();

            if (joinedPlans.contains(planConfig.getPlanCfgId())){
                personDetailPlan.setJoin(true);
            }
            else {
                personDetailPlan.setJoin(false);
            }

            planConfig.setSimple(false);
            if (StringUtils.isEmpty(planConfig.getPlanCfgFlowId())){
                planConfig.setSimple(true);
            }

            personDetailPlan.setPlanConfig(planConfig);

            /// 读取计划详情
            List<PlanDetailConfig> planDetailConfigs = planConfigDetailService.selectPlanItemByPlanId(planConfig.getPlanCfgId().longValue());

            List<String> tmpNames = new ArrayList<>();
            for (PlanDetailConfig cfg:planDetailConfigs){
                tmpNames.add(cfg.getPlanCfgItemName());
            }

            personDetailPlan.setItemNames(tmpNames);
            personDetailPlan.setDetailConfig(planDetailConfigs);
            perPlanInfos.add(personDetailPlan);
        }

        result.setPerPlanInfos(perPlanInfos);
        return result;
    }


    @RequiresPermissions("personal:sign:list")
    @RequestMapping("/list/detail")
    @ResponseBody
    public  Map<String,Object>  list(@RequestParam(name="id") String id)
    {
        Map<String,Object> res =new LinkedHashMap<>();

        /// 读取计划详情
        Long longId = 0L;
        try{
            longId = Long.parseLong(id);
        }
        catch (Exception e){
            return  res;
        }
        List<PlanDetailConfig> planDetailConfigs = planConfigDetailService.selectPlanItemByPlanId(longId);

        if (null == planDetailConfigs){
            return  res;
        }

        List<PlanClass> planClasses =new ArrayList<>();
        List<PlanCustom> planCustoms =new ArrayList<>();
        List<PlanAchievement> planAchievements =new ArrayList<>();
        List<SysDictData> planClassTypes= sysDictDataService.selectDictDataByType("plan_class_type");
        Map<String,String> classTypeInfo = new HashMap<>();
        //配置课程类型
        for (SysDictData data:planClassTypes){
            classTypeInfo.put(data.getDictValue(),data.getDictLabel());
        }

        for (PlanDetailConfig config:planDetailConfigs) {
            if (null == config.getPlanCfgItemType()){
                continue;
            }
            if (config.getPlanCfgItemType().toString().equals(PerConstants.PLAN_TYPE_CLASS)){
                PlanClass planClass = planClassService.selectPlanClassById(config.getPlanCfgItemId().longValue());
                if (null != planClass){
                    if (planClass.getPlanClassType() != null && classTypeInfo.containsKey(planClass.getPlanClassType())){
                        planClass.setPlanClassType(classTypeInfo.get(planClass.getPlanClassType()));
                    }

                    planClass.setWeight(config.getPlanCfgItemWeight().toPlainString());
                    planClasses.add(planClass);
                }
            }

            if (config.getPlanCfgItemType().toString().equals(PerConstants.PLAN_TYPE_CUSTOM)){
                PlanCustom planCustom = planCustomService.selectPlanCusById(config.getPlanCfgItemId().longValue());
                if (null != planCustom){
                    planCustom.setWeight(config.getPlanCfgItemWeight().toPlainString());
                    planCustoms.add(planCustom);
                }
            }

            if (config.getPlanCfgItemType().toString().equals(PerConstants.PLAN_TYPE_PERFORMANCE)){
                PlanAchievement planAchievement = planArchService.selectPlanAchById(config.getPlanCfgItemId().longValue());
                if (null != planAchievement){
                    planAchievement.setWeight(config.getPlanCfgItemWeight().toPlainString());
                    planAchievements.add(planAchievement);
                }
            }
        }

        List<SysDictData> perfScores= sysDictDataService.selectDictDataByType("plan_achievement_score");

        List<Map<String,String>> perfScoreInfo = new ArrayList<>();
        //配置课程类型
        for (SysDictData data:perfScores){
            Map<String,String> dictInfo = new LinkedHashMap<>();
            dictInfo.put("level",data.getDictLabel());
            dictInfo.put("score",data.getDictValue());
            perfScoreInfo.add(dictInfo);
        }

        res.put("performance",planAchievements);
        res.put("customFiled",planCustoms);
        res.put("planClass",planClasses);
        res.put("perfConfig",perfScoreInfo);
        return  res;
    }

    /**
     * 新增用户
     */
    @GetMapping("/add")
    public String add(ModelMap mmap)
    {
        return prefix + "/add";
    }

    @RequiresPermissions("personal:sign:add")
    @PostMapping("/add/simple")
    @Transactional(rollbackFor = Exception.class)
    @ResponseBody
    public AjaxResult addSimpleSave(@RequestParam(name = "planId") String planId,@RequestParam(name = "remark", required = false) String remark){
        return addSave(planId,null,remark);
    }

    @RequiresPermissions("personal:sign:add")
    @PostMapping("/add")
    @Transactional(rollbackFor = Exception.class)
    @ResponseBody
    public AjaxResult addSave(@RequestParam(name = "planId") String planId
            ,  @RequestParam("file")  MultipartFile file,@RequestParam(name = "remark", required = false) String remark
    )
    {
        try
        {
            SysUser user = ShiroUtils.getSysUser();

            Integer planIdNum = 0;
            try{
                planIdNum = Integer.parseInt(planId);
            }
            catch (Exception e)
            {
                return error("计划编码的格式不正确");
            }

            List<PersonalSign> personalSigns = personalSignService.querySignListByUserId(user.getUserId().intValue());

            if (!CollectionUtils.isEmpty(personalSigns)){
                for (PersonalSign sign:personalSigns ) {
                    if (planIdNum.equals(sign.getPerSignPlanId())){
                        return error("已经报名过该计划");
                    }
                }
            }

            // 调用计划查询服务查询计划ID是否存在
            PlanConfig config = planConfigService.selectPlanConfigById(planIdNum.longValue());

            if (config == null || !config.getPlanCfgStatus().equalsIgnoreCase(PerConstants.PLAN_RELEASE_STATUS)){
                return  error("计划不存在,或已经过期");
            }

            if (config.getPlanCfgStartTime() != null && config.getPlanCfgStartTime().after(new Date())){
                return  error("计划还没有开始");
            }

            if (config.getPlanCfgEndTime() != null && config.getPlanCfgEndTime().before(new Date())){
                return  error("计划已经结束");
            }

            config.setSimple(false);
            if (StringUtils.isEmpty(config.getPlanCfgFlowId())){
                config.setSimple(true);
            }

            String filePath = null;
            if (!config.isSimple()){
                if (file != null && !file.isEmpty())
                {
                    filePath = FileUploadUtils.upload(Global.getApplyPath(), file);
                }
                else {
                    return error("请上传报名文件");
                }
            }

            PersonalSign sign= new PersonalSign();
            sign.setPerSignPlanId(planIdNum);
            sign.setPerSignUserId(user.getUserId().intValue());
            sign.setPerSignUpdateUser(user.getUserId().intValue());

            if (!StringUtils.isEmpty(remark)){
                sign.setRemark(remark);
            }

            if (!config.isSimple()){
                filePath=Global.getApplyPath()+filePath;
                sign.setApplyFile(filePath.replace("\\","/"));
                int num = personalSignService.addSignInfo(sign);

                if (num == 0){
                    return error("添加报名信息失败");
                }

                ProcessInstance processInstance = baseService.createFlow(ShiroUtils.getSysUser(),planIdNum.toString(),remark);
                sign.setProcessId(processInstance.getId());
                num = personalSignService.updateUser(sign);
                return toAjax(num);
            }
            else {
                sign.setResult("1");

                int num = personalSignService.addSignInfo(sign);

                return toAjax(num);
            }

        }
        catch (Exception e){
            log.error("报名发生异常",e);
            return error("报名发生异常"+e.getMessage());
        }

    }
}
